#include "include/native_codec_handle.h"

namespace codec {
static jclass g_stateClass = nullptr;
NativeCodecHandler::~NativeCodecHandler() {
  if (_callback != nullptr) {
    JNIEnv *env = jniEnv();
    env->DeleteGlobalRef(_callback);
  }
}

void NativeCodecHandler::setDataSource(int fd) {
  JNIEnv *env = jniEnv();
  jclass localClass =
      env->FindClass("com/bzsg/simpleMediaPlayer/data/PlayerStateCode");
  if (!localClass) {
    env->ExceptionClear();  // 必须清除异常
  }

  g_stateClass = (jclass)env->NewGlobalRef(localClass);  // 创建全局引用
  env->DeleteLocalRef(localClass);                       // 删除局部引用
  stateManager->setDataSource(fd);
}

void NativeCodecHandler::prepare(ANativeWindow *window,
                                 const std::string &vertexCode,
                                 const std::string &fragmentCode) {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "papre");
  stateManager->prepare(window, vertexCode, fragmentCode);
}

void NativeCodecHandler::start() {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "start");
  stateManager->start();
}

void NativeCodecHandler::release() {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "release");
  stateManager->release();
}

void NativeCodecHandler::ChangeSurface(int width, int height,
                                       bool isFullScreen) {}
void NativeCodecHandler::pause() {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "pause");
  stateManager->pause();
}
void NativeCodecHandler::resume() {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "resume");
  stateManager->resume();
}
void NativeCodecHandler::stop() {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "stop");
}
void NativeCodecHandler::seekTo(float position) {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "seekTo");
  stateManager->seekTo(position);
}
void NativeCodecHandler::setCallback(jobject callbackObj) {
  __android_log_print(ANDROID_LOG_INFO, TAG_.c_str(), "callback");
  JNIEnv *env = jniEnv();
  _callback = env->NewGlobalRef(callbackObj);
  stateManager->setCallback([&](PlayerStateCode code,
                                const std::map<std::string, std::string> &map) {
    JNIEnv *env = jniEnv();

    // 获取枚举类

    const char *fieldName = "INITIALIZED";
    switch (code) {
      case PlayerStateCode::IDLE:
        fieldName = "IDLE";
        break;
      case PlayerStateCode::INITIALIZED:
        fieldName = "INITIALIZED";
        break;
      case PlayerStateCode::PREPARED:
        fieldName = "PREPARED";
        break;
      case PlayerStateCode::PLAYING:
        fieldName = "PLAYING";
        break;
      case PlayerStateCode::PAUSED:
        fieldName = "PAUSED";
        break;
      case PlayerStateCode::SEEKING:
        fieldName = "SEEKING";
        break;
      case PlayerStateCode::COMPLETED:
        fieldName = "COMPLETED";
        break;
      case PlayerStateCode::STOPPED:
        fieldName = "STOPPED";
        break;
      case PlayerStateCode::ERROR:
        fieldName = "ERROR";
        break;
      default:
        __android_log_print(ANDROID_LOG_WARN, "fhq",
                            "error PlayerStateCode check it");
    }
    // 获取静态枚举字段
    jfieldID fieldID = env->GetStaticFieldID(
        g_stateClass, fieldName,
        "Lcom/bzsg/simpleMediaPlayer/data/PlayerStateCode;");
    jobject stateObj = env->GetStaticObjectField(g_stateClass, fieldID);
    jclass bundleClass = env->FindClass("android/os/Bundle");
    jmethodID bundleInit = env->GetMethodID(bundleClass, "<init>", "()V");
    jobject bundle = env->NewObject(bundleClass, bundleInit);

    // 添加数据到 Bundle
    jmethodID putString = env->GetMethodID(
        bundleClass, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");

    if (putString == nullptr) {
      env->DeleteLocalRef(bundleClass);
      return;
    }

    for (const auto &[key, value] : map) {
      jstring jKey = env->NewStringUTF(key.c_str());
      jstring jValue = env->NewStringUTF(value.c_str());

      if (jKey && jValue) {
        env->CallVoidMethod(bundle, putString, jKey, jValue);
      }

      if (jKey) env->DeleteLocalRef(jKey);
      if (jValue) env->DeleteLocalRef(jValue);
    }

    env->CallVoidMethod(_callback, gCallbackInfo.onStateChanged, stateObj,
                        bundle);
    // env->DeleteLocalRef(g_stateClass);
    env->DeleteLocalRef(stateObj);
    env->DeleteLocalRef(bundleClass);
    env->DeleteLocalRef(bundle);
  });
}
}  // namespace codec